﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace FriendlyFireLibrary
{
    public class NetworkCodeServer
    {
        Socket client;
        IPEndPoint clientep;
        Socket newsock;
        public string status;
        public NetworkCodeServer()
        {
            StartServerSocket();
        }

        private void StartServerSocket()
        {
            IPEndPoint ipep = new IPEndPoint(IPAddress.Any,
                         44299);
            newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            newsock.Bind(ipep);
            newsock.Listen(10);
        }
        public void SendFile(string sendFile)
        {
            FileStream stream = File.Open(sendFile, FileMode.Open);
            
            //Send File Size
            byte[] initialData = new byte[8];
            long totalSize = stream.Length;
            initialData = BitConverter.GetBytes(totalSize);
            client.Send(initialData, initialData.Length, SocketFlags.None);

            //Send File Name Size
            string fileName = Path.GetFileName(sendFile);
            byte[] filenameSize = new byte[4];
            int fnSize = fileName.Length;
            filenameSize = BitConverter.GetBytes(fnSize);
            client.Send(filenameSize, filenameSize.Length, SocketFlags.None);

            byte[] fileData = new byte[fnSize];
            fileData = Encoding.ASCII.GetBytes(fileName);
            client.Send(fileData,0,fnSize, SocketFlags.None);

            long sent = 0;
            while (sent < totalSize)
            {
                byte[] data = new byte[1024];
                int i = 1024;
                for (int j = 0; j < 1024; j++)
                    if (stream.CanRead)
                        data[j] = (byte)stream.ReadByte();
                    else
                    {
                        i = j;
                        break;
                    }
                client.Send(data, i, SocketFlags.None);
                sent += 1024;
            }
            stream.Close();
        }
        public void AcceptClients()
        {
            //Waiting for a client...
            client = newsock.Accept();
            clientep = (IPEndPoint)client.RemoteEndPoint;
            status = "Connected with " + clientep.Address + "at port " + clientep.Port;
        }
        public void SendMessage(string message)
        {
            byte[] data = new byte[1024];
            data = Encoding.ASCII.GetBytes(message);
            client.Send(data, data.Length, SocketFlags.None);
        }
        public void Shutdown()
        {
            client.Close();
            newsock.Close();
        }
    }

    public class NetworkCodeClient
    {
        Socket server;
        public string status;
        public NetworkCodeClient(string IP)
        {
            StartClientSocket(IP);
        }

        private void StartClientSocket(string IP)
        {
            IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(IP), 44299);
            server = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
            try
            {
                server.Connect(ipep);
            }
            catch (SocketException a)
            {
                status = "Unable to connect to server." + Environment.NewLine + a.ToString();
                return;
            }
        }

        public string ReceiveMessage()
        {
            byte[] data = new byte[1024];
            string stringData;
            int recv = server.Receive(data);
            stringData = Encoding.ASCII.GetString(data, 0, recv);
            return stringData;
        }

        public string ReceiveFile(string directory)
        {
            byte[] initialData = new byte[8];
            int recv = server.Receive(initialData,0, 8, SocketFlags.None);
            long totalSize = BitConverter.ToInt64(initialData, 0);

            byte[] fileNameSize = new byte[4];
            recv = server.Receive(fileNameSize, 0, 4, SocketFlags.None);
            int fileSizeName = BitConverter.ToInt32(fileNameSize, 0);

            byte[] fileName = new byte[fileSizeName];
            recv = server.Receive(fileName, SocketFlags.None);
            string name = Encoding.ASCII.GetString(fileName,0, fileSizeName);

            long sizeReceived = 0;
            byte[] data = new byte[1024];
            FileStream stream = File.Create(directory + @"\" + name);
            while (sizeReceived < totalSize)
            {
                recv = server.Receive(data);
                sizeReceived += recv;
                if(stream.CanWrite)
                    stream.Write(data, 0, recv);
            }
            stream.Close();
            return name;
        }

        public void Shutdown()
        {
            status = "Disconnecting from server...";
            server.Shutdown(SocketShutdown.Both);
            server.Close();
        }
    }
}
